#include "cc_window.h"
#include <iostream>


CCWindow::CCWindow(QWidget *parent) : QMainWindow(parent), m_clipBox_(nullptr) //,m_sql_(nullptr)
{
    m_mdiArea_ = new QMdiArea(parent);
    setCentralWidget(m_mdiArea_);
    this->setWindowFlags(Qt::FramelessWindowHint);
    m_mdiArea_->installEventFilter(this);
    new3DView(true);
    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setMaximumSize(771,431);
    this->setMinimumSize(771,431);
  
}

CCWindow::~CCWindow()
{
}

ccGLWindow *CCWindow::getActiveGLWindow()
{
    if (!m_mdiArea_)
    {
        return 0;
    }

    QMdiSubWindow *activeSubWindow = m_mdiArea_->activeSubWindow();
    if (activeSubWindow)
    {
        return GLWindowFromWidget(activeSubWindow->widget());
    }
    else
    {
        QList<QMdiSubWindow *> subWindowList = m_mdiArea_->subWindowList();
        if (!subWindowList.isEmpty())
        {
            return GLWindowFromWidget(subWindowList[0]->widget());
        }
    }

    return 0;
}

ccGLWindow *CCWindow::new3DView(bool allowEntitySelection)
{
    // assert(m_ccRoot && m_mdiArea);

    QWidget *viewWidget = nullptr;
    ccGLWindow *view3D = nullptr;

    CreateGLWindow(view3D, viewWidget, false);

    if (!viewWidget || !view3D)
    {
        qDebug() << "[3D] Failed to create the 3D view";
        assert(false);
        return nullptr;
    }
    QString m_shader_path = QCoreApplication::applicationDirPath();

    view3D->setShaderPath(m_shader_path);
    view3D->setAutoPickPivotAtCenter(true);

    viewWidget->setMinimumSize(400, 300);

    m_mdiArea_->addSubWindow(viewWidget);


    viewWidget->setAttribute(Qt::WA_DeleteOnClose);

    viewWidget->showMaximized();
    viewWidget->update();
    return view3D;
}

void CCWindow::addToDB(ccHObject *entity, ccGLWindow *detWin)
{
    assert(entity && detWin);

    entity->setDisplay_recursive(detWin);

    ccHObject *currentRoot = detWin->getSceneDB();
    if (currentRoot)
    {
        //already a pure 'root'
        if (currentRoot->isA(CC_TYPES::HIERARCHY_OBJECT))
        {
            currentRoot->addChild(entity);
        }
        else
        {
            ccHObject *root = new ccHObject("root");
            root->addChild(currentRoot);
            root->addChild(entity);
            detWin->setSceneDB(root);
        }
    }
    else
    {
        detWin->setSceneDB(entity);
    }
    return;
}

void CCWindow::activeClipBox()
{
    ccGLWindow *win = getActiveGLWindow();
    if (!win)
    {
        return;
    }
    if (m_clipBox_)
    {
        m_clipBox_->releaseAssociatedEntities();
    }
    if (!m_clipBox_)
    {
        m_clipBox_ = new ccClipBox("clipbox");
    }
    m_clipBox_->setEnabled(true);
    m_clipBox_->setSelected(true);
    addToDB(m_clipBox_, win);
    // getSelectedEntities();
    // for (ccHObject *entity : m_visibleEntities_)
    // {
    //     m_clipBox_->addAssociatedEntity(entity);
    // }
}

void CCWindow::removeFromDB(ccHObject *entity, ccGLWindow *detWin)
{

    assert(entity && detWin);

    if (entity->getDisplay())
    {
        static_cast<ccGLWindow *>(entity->getDisplay())->removeFromOwnDB(entity);
    }

    delete entity;
    entity = nullptr;
}

void CCWindow::setPointCloud(const pcl::PointCloud<pcl::PointXYZ>::Ptr pt)
{
    ccGLWindow *detWin = getActiveGLWindow();

    // qDebug() << "pc size: " << pt->points.size();

    int vec_count = ceil(pt->points.size() / 9900000.0);
    float r = 0;
    float g = 0;
    float b = 0;
    ccColor::Rgb rgb;

    std::vector<ccHObject *> group_vec;
    for (int i = 0; i < vec_count; i++)
    {
        ccHObject *group = ccHObject::New(CC_TYPES::POINT_CLOUD, "pc");
        group_vec.push_back(group);
        addToDB(group, detWin);
    }

    float min_z = 0.0;
    float max_z = 1.0;

    for (unsigned int i = 0; i < pt->points.size(); i++)
    {
        if (pt->points[i].z > max_z)
            max_z = pt->points[i].z;
        if (pt->points[i].z < min_z)
            min_z = pt->points[i].z;
    }

    for (unsigned int i = 0; i < pt->points.size(); i++)
    {

        CCVector3 P;
        P.x = pt->points[i].x;
        P.y = pt->points[i].y;
        P.z = pt->points[i].z;
        // getColorRamp(-1, 10, P.z, r, g, b);
        getColorRamp(min_z, max_z, P.z, r, g, b);
        rgb = ccColor::Rgb(r * 255, g * 255, b * 255);
        int index = i / 9900000;
        ccPointCloud *pc = static_cast<ccPointCloud *>(group_vec[index]);
        pc->addPoint(P);
        pc->resizeTheRGBTable(true);
        pc->setPointColor(pc->size() - 1, rgb);
        pc->showColors(true);
    }

    // detWin->onWheelEvent(50.0f);
    detWin->redraw();
    m_muti_group_vec_.push_back(group_vec);
    activeClipBox();
}

void CCWindow::clearPointCloud()
{
    ccGLWindow *detWin = getActiveGLWindow();
    // 清除pc
    if (m_muti_group_vec_.size() > 0)
    {
        for(int index = 0; index < m_muti_group_vec_.size(); index++){
            for (auto &obj : m_muti_group_vec_[index])
            {
                removeFromDB(obj, detWin);
            }
            m_muti_group_vec_.erase(m_muti_group_vec_.begin() + index);
        }
        
    }
}

void CCWindow::getColorRamp(float minz, float maxz, float pz, float &r, float &g, float &b)
{

    r = 0;
    g = 0;
    b = 1;
    float index = (pz - minz) / (maxz - minz) * 8.;
    if (index <= 2.)
    {
        r = 0;
        g = index * 0.5;
        b = 1;
    }
    else if (index > 2. && index <= 4.)
    {
        r = 0;
        g = 1;
        b = 1 - (index - 2) * 0.5;
    }
    else if (index > 4. && index <= 6.)
    {
        r = (index - 4) * 0.5;
        g = 1;
        b = 0;
    }
    else if (index > 6. && index <= 8.)
    {
        r = 1;
        g = 1 - (index - 6) * 0.5;
        b = 0;
    }
    else
    {
        r = 1;
        g = 0;
        b = 0;
    }
}